/* 
 * File:   OperacionSincronizacionArchivosEliminados.cpp
 * Author: maximiliano
 * 
 * Created on 15 de junio de 2013, 10:41
 */

#include "client_OperacionSincronizacionArchivosEliminados.h"
#include "client_OperacionCargaArchivo.h"
#include "client_OperacionEliminarArchivoCliente.h"
#include "client_OperacionEliminarArchivoServidor.h"
#include "client_OperacionDescargaArchivo.h"
#include "client_OperacionEliminarArchivoCliente.h"
#include "client_OperacionEliminarArchivoServidor.h"
#include "common_TokenFactory.h"

using namespace TP::Comunicacion;
using namespace TP::Operaciones;

OperacionSincronizacionArchivosEliminados::OperacionSincronizacionArchivosEliminados(const uint32_t &pToken, Repositorio **pRepositorioLocal, Repositorio **pRepositorioServidor, FileServiceProxy* pFileService) : OperacionSecuencial(pToken) {
    
    _repositorioLocal = pRepositorioLocal;
    _repositorioServidor = pRepositorioServidor;
    _fileService = pFileService;
    
    this->setFinalizada(true);
}

OperacionSincronizacionArchivosEliminados::~OperacionSincronizacionArchivosEliminados() {}

void OperacionSincronizacionArchivosEliminados::ejecutar(){
    
    /* Se calcula el esquema de trabajo.  Esto es, las operaciones que tiene que
     * ejecutar el secuencia la operacion de sincronizacion a fin de llevar
     * a cabo de forma satisfactoria la sincronizacion de repositorios.
     */
    this->CalcularEsquemaTrabajo();
    
    /* Se ejecuta el proceso de trabajo.
     */
    OperacionSecuencial::ejecutar();
    
}

void OperacionSincronizacionArchivosEliminados::CalcularEsquemaTrabajo(){
    
    this->LimpiarOperaciones();
    
    this->CalcularEsquemaTrabajoArchivosAEliminarEnCliente();
    
    this->CalcularEsquemaTrabajoArchivosAEliminarEnServidor();
}

SetRepoItem OperacionSincronizacionArchivosEliminados::getArchivosAEliminarEnCliente(){
    
    SetRepoItem items;
    
    RepoItem* itemLocal = (*_repositorioLocal)->Primero();
    
    while (NULL != itemLocal)
    {
        if (ARCHIVO_A_ELIMINAR_EN_CLIENTE == itemLocal->GetEstado())
        {
            items.push_back(itemLocal);
        }
        
        itemLocal = (*_repositorioServidor)->Siguiente(itemLocal);
    }
    
    return items;
}

SetRepoItem OperacionSincronizacionArchivosEliminados::getArchivosAEliminarEnServidor(){
    
    SetRepoItem items;
    SetRepoItemIterator itRepoLocal = (*_repositorioLocal)->GetItemIterator();
    
    while (itRepoLocal < (*_repositorioLocal)->GetItemIteratorEnd())
    {
        if (ARCHIVO_A_ELIMINAR_EN_SERVIDOR == (*itRepoLocal)->GetEstado())
        {
            items.push_back(*itRepoLocal);
        }
        itRepoLocal++;
    }
    
    return items;
}

void OperacionSincronizacionArchivosEliminados::CalcularEsquemaTrabajoArchivosAEliminarEnServidor(){
 
    // Configura el esquema de trabajo de descarga de archivos nuevos desde el servidor.

    SetRepoItem archivosADescargar = this->getArchivosAEliminarEnServidor();
    SetRepoItemIterator itADescargar = archivosADescargar.begin();

    while (itADescargar < archivosADescargar.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionEliminarArchivoServidor
                (
                  TokenFactory::Crear()
                , _fileService
                , (*_repositorioLocal)
                , (*itADescargar)->GetFilename()
                , (*itADescargar)->GetVersion()
                )
        );
        
        itADescargar++;
    }
    
    archivosADescargar.clear();
}

void OperacionSincronizacionArchivosEliminados::CalcularEsquemaTrabajoArchivosAEliminarEnCliente(){
 
    // Configura el esquema de trabajo de carga de archivos desde el cliente.
    
    vector<RepoItem*> archivosAEliminar = this->getArchivosAEliminarEnCliente();
    vector<RepoItem*>::iterator itArchivosAEliminar = archivosAEliminar.begin();
    
    while (itArchivosAEliminar < archivosAEliminar.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionEliminarArchivoCliente
            (
              TokenFactory::Crear()
            , _fileService
            , (*_repositorioLocal)
            , (*itArchivosAEliminar)->GetFilename()
            , (*itArchivosAEliminar)->GetVersion()
            )
        );
        
        itArchivosAEliminar++;
    }
    
    archivosAEliminar.clear();
}